﻿using CasignDesignGA.Casign;
using CasignDesignGA.Casing;
using CasignDesingGA.Casing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CasignDesignGA.Engine.Reproduction
{
    class CrossOverAlgorithm : IReproductionAlgorithm
    {
        private static CrossOverAlgorithm instance;

        private CrossOverAlgorithm() { }

        public static CrossOverAlgorithm Instance
        {
           get 
           {
              if (instance == null)
               {
                  instance = new CrossOverAlgorithm();
               }
               return instance;
             }
         }

        public Population.Population performCrossover(Population.Population selectedIndividuals)
        {
            Population.Population newPopulation = new Population.Population();
            
            for (int i = 0; i < (selectedIndividuals.count()); i = i + 2)
            {
                

                ISelectable firstParent = selectedIndividuals.getIndividualIndex(i);
                ISelectable secondParent = selectedIndividuals.getIndividualIndex(i + 1);
                if (firstParent != null && secondParent != null)
                {
                    newPopulation.Add(crossover(firstParent, secondParent));
                }
            }

            return newPopulation;
        }
        private Population.Population crossover(ISelectable firstParentIndividual, ISelectable secondParentIndividual)
        {
            Population.Population newPopulation = new Population.Population();


            CasingDesign firstParent = (CasingDesign)firstParentIndividual;
            CasingDesign secondParent = (CasingDesign)secondParentIndividual;

            CasingUnit firstParentFirstCasing = firstParent.CasingCollection[0];
            CasingUnit firstParentSecondCasing = firstParent.CasingCollection[1];
            CasingUnit secondParentFirstCasing = secondParent.CasingCollection[0];
            CasingUnit secondParentSecondCasing = secondParent.CasingCollection[1];
            
            CasingDesign firstNewSibling = new CasingDesign();
            CasingDesign secondNewSibling = new CasingDesign();
            CasingDesign thirdNewSibling = new CasingDesign();
            CasingDesign fourthNewSibling = new CasingDesign();

            /*First Sibling*/
            CasingUnit firstParentFirstCasingClone = firstParentFirstCasing.Clone();
            firstParentFirstCasingClone.Longitude = firstParentFirstCasing.Longitude;

            CasingUnit secondParentSecondCasingClone = secondParentSecondCasing.Clone();
            secondParentSecondCasingClone.Longitude = firstParentSecondCasing.Longitude;

            firstNewSibling.CasingCollection.Add(firstParentFirstCasingClone);
            firstNewSibling.CasingCollection.Add(secondParentSecondCasingClone);

            /*Second Sibling*/
            CasingUnit secondParentFirstCasingClone = secondParentFirstCasing.Clone();
            secondParentFirstCasingClone.Longitude = secondParentFirstCasing.Longitude;

            CasingUnit firstParentSecondCasingClone = firstParentSecondCasing.Clone();
            firstParentSecondCasingClone.Longitude = secondParentSecondCasing.Longitude;

            secondNewSibling.CasingCollection.Add(secondParentFirstCasingClone);
            secondNewSibling.CasingCollection.Add(firstParentSecondCasingClone);

            /*Third Sibling*/
            CasingUnit firstParentFirstCasingClone2 = firstParentFirstCasing.Clone();
            firstParentFirstCasingClone2.Longitude = secondParentFirstCasing.Longitude;

            CasingUnit secondParentSecondCasingClone2 = secondParentSecondCasing.Clone();
            secondParentSecondCasingClone2.Longitude = secondParentSecondCasing.Longitude;

            thirdNewSibling.CasingCollection.Add(firstParentFirstCasingClone2);
            thirdNewSibling.CasingCollection.Add(secondParentSecondCasingClone2);

            /*Fourth sibling*/
            CasingUnit secondParentFirstCasingClone2 = secondParentFirstCasing.Clone();
            secondParentFirstCasingClone2.Longitude = firstParentFirstCasing.Longitude;

            CasingUnit firstParentSecondCasingClone2 = firstParentSecondCasing.Clone();
            firstParentSecondCasingClone2.Longitude = firstParentSecondCasing.Longitude;

            fourthNewSibling.CasingCollection.Add(secondParentFirstCasingClone2);
            fourthNewSibling.CasingCollection.Add(firstParentSecondCasingClone2);

            newPopulation.Add(firstNewSibling);
            newPopulation.Add(secondNewSibling);
            newPopulation.Add(thirdNewSibling);
            newPopulation.Add(fourthNewSibling);
            
            return newPopulation;
        }
    }
}
